using System;
using System.Linq;
using System.Threading.Tasks;
using Abp.Configuration;
using Abp.Extensions;
using Abp.Runtime.Session;
using Abp.UI;
using Abp.Zero.Configuration;
using Microsoft.AspNetCore.Identity;
using Vecen.BangChuang.Authorization.Accounts.Dto;
using Vecen.BangChuang.Authorization.Users;
using Vecen.BangChuang.BangChuang.Areas;
using Vecen.BangChuang.BangChuang.Common;
using Vecen.BangChuang.BangChuang.DomainServices.Agents;
using Vecen.BangChuang.BangChuang.DomainServices.Common;

namespace Vecen.BangChuang.Authorization.Accounts {
    /// <summary>
    /// 
    /// </summary>
    public class AccountAppService: BangChuangAppServiceBase, IAccountAppService {
        private readonly UserRegistrationManager _userRegistrationManager;
        private readonly ValidationCodeDomainService _validationCodeDomainService;
        private readonly CityDomainService _cityDomainService;
        private readonly AgentDomainService _agentDomainService;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="userRegistrationManager"></param>
        /// <param name="validationCodeDomainService"></param>
        /// <param name="cityDomainService"></param>
        /// <param name="agentDomainService"></param>
        public AccountAppService(UserRegistrationManager userRegistrationManager,
            ValidationCodeDomainService validationCodeDomainService,
            CityDomainService cityDomainService,
            AgentDomainService agentDomainService) {
            _userRegistrationManager = userRegistrationManager;
            _validationCodeDomainService = validationCodeDomainService;
            _cityDomainService = cityDomainService;
            _agentDomainService = agentDomainService;
        }

        /// <summary>
        /// 检查推荐人信息是否可用
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public Task<IsRecommendAvailableOutPut> IsRecommendAvailable(IsRecommendAvailableInput input) {
            IsRecommendAvailableOutPut outPut = new IsRecommendAvailableOutPut();
            return Task.Run(() => {
                outPut.IsAvailable =
                    UserManager.Users.Any(c => c.PhoneNumber == input.PhoneNumber || c.WeChat == input.WeChat);

                return outPut;
            });
        }

        /// <summary>
        /// 检查用户手机是否可用
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public Task<IsUserAvailableOutPut> IsUserAvailable(IsUserAvailableInput input) {
            IsUserAvailableOutPut outPut = new IsUserAvailableOutPut();
            return Task.Run(() => {
                outPut.IsAvailable = !UserManager.Users.Any(c => c.PhoneNumber == input.PhoneNumber);

                return outPut;
            });
        }

        /// <summary>
        /// 检查租户名称是否可用
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [Obsolete]
        public async Task<IsTenantAvailableOutput> IsTenantAvailable(IsTenantAvailableInput input) {
            var tenant = await TenantManager.FindByTenancyNameAsync(input.TenancyName);
            if(tenant == null) {
                return new IsTenantAvailableOutput(TenantAvailabilityState.NotFound);
            }

            if(!tenant.IsActive) {
                return new IsTenantAvailableOutput(TenantAvailabilityState.InActive);
            }

            return new IsTenantAvailableOutput(TenantAvailabilityState.Available, tenant.Id);
        }

        /// <summary>
        /// 注册
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [Obsolete]
        public async Task<RegisterOutput> Register(RegisterInput input) {
            var user = await _userRegistrationManager.RegisterAsync(input.Name, input.Surname, input.EmailAddress,
                input.UserName, input.Password, false);

            var isEmailConfirmationRequiredForLogin =
                await SettingManager.GetSettingValueAsync<bool>(AbpZeroSettingNames.UserManagement
                    .IsEmailConfirmationRequiredForLogin);

            return new RegisterOutput {
                CanLogin = user.IsActive && (user.IsEmailConfirmed || !isEmailConfirmationRequiredForLogin),
                UserId = user.Id
            };
        }

        /// <summary>
        /// 注册
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<RegisterOutput> RegisterAsync(RegisterRequestDto input) {
            if(!input.RecommendPhoneNumber.IsNullOrWhiteSpace()) {
                var isRecommendAvailable = await IsRecommendAvailable(new IsRecommendAvailableInput()
                    {PhoneNumber = input.RecommendPhoneNumber, WeChat = input.WeChat});
                if(!isRecommendAvailable.IsAvailable) {
                    throw new UserFriendlyException("注册失败!", "推荐人信息不存在!");
                }
            }
            var isUserAvailable = await IsUserAvailable(new IsUserAvailableInput()
                {PhoneNumber = input.PhoneNumber, WeChat = input.WeChat});
            if(!isUserAvailable.IsAvailable) {
                throw new UserFriendlyException("注册失败!", "用户手机号已被注册!");
            }

            var recommend =
                await Task.Run(
                    () => UserManager.Users.FirstOrDefault(c => c.PhoneNumber == input.RecommendPhoneNumber));
            var user = await _userRegistrationManager.RegisterAsync(input.PhoneNumber, input.ValidationCode,
                input.Password);
            user.WeChat = input.WeChat;
            user.Recommend = recommend?.Id;
            user.AreaCode = _cityDomainService.GetAreaId(input.ProvinceId, input.CityId, input.DistrictId);
            await UserManager.UpdateAsync(user);

            if(recommend != null) {
                var recommendAgent = await _agentDomainService.GetByUserIdAsync(recommend.Id);
                if(recommendAgent != null) {
                    await _agentDomainService.AddClientToAgentAsync(user.Id, recommendAgent.Id);
                }
            }
            return new RegisterOutput {UserId = user.Id, CanLogin = true};
        }

        /// <summary>
        /// 发送验证码
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task SendValidationCode(SendCodeRequestDto input) {
            await _validationCodeDomainService.SendValidationCode(input.PhoneNumber,
                new Random(DateTime.Now.Millisecond).Next(100000, 999999).ToString(), input.CodeType);
        }

        /// <summary>
        /// 修改密码
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task ChangePasswordAsync(PasswordChangeInput input) {
            User user;
            if(AbpSession.UserId.HasValue) {
                user = await UserManager.GetUserByIdAsync(AbpSession.GetUserId());
                if(string.IsNullOrWhiteSpace(input.PhoneNumber)) {
                    input.PhoneNumber = user.PhoneNumber;
                }
            } else {
                user = await Task.Run(() => UserManager.Users.FirstOrDefault(c => c.PhoneNumber == input.PhoneNumber));
            }

            if(user == null) {
                throw new UserFriendlyException("修改密码出错!", "用户不存在!");
            }

            if(input.PhoneNumber.IsNullOrWhiteSpace()) {
                throw new UserFriendlyException("修改密码出错!", "手机号不能为空!");
            }
            if(!await _validationCodeDomainService.ValidationAsync(input.PhoneNumber, input.ValidationCode,
                ValidationCodeType.ChangePassword)) {
                throw new UserFriendlyException("修改密码出错!", "验证码不正确!");
            }
            user.Password = new PasswordHasher<User>().HashPassword(user, input.NewPassword);
            await UserManager.UpdateAsync(user);
        }
    }
}